<?php

$loader->requireOnce('includes/PatientQueue/AbsQueue.class.php');
/**
 *
 * Object Relational Persistence Mapping Class for table: queue_item
 *
 * @package	com.clearhealth
 * @author	ClearHealth Inc.
 */
class QueueItem extends ORDataObject {

	/**#@+
	 * Fields of table: queue_item mapped to class members
	 */
	var $queue_item_id		= '';
	var $queue_id		= '';
	var $patient_id		= '';
	var $ticket_item_id		= '';
	var $room_id		= '';
	var $ticket_id		= '';
	var $start_waiting		= '';
	var $holder_id		= '';
	/**#@-*/


	/**
	 * DB Table
	 */
	var $_table = 'queue_item';

	/**
	 * Primary Key
	 */
	var $_key = 'queue_item_id';

	/**
	 * Internal Name
	 */
	var $_internalName = 'QueueItem';

	/**
	 * Handle instantiation
	 */
	function QueueItem() {
		parent::ORDataObject();
	}


	/**#@+
	 * Field: start_waiting, time formatting
	 */
	function get_start_waiting() {
		return $this->_getDate('start_waiting');
	}
	function set_start_waiting($date) {
		$this->_setDate('start_waiting',$date);
	}
	/**#@-*/

	public static function fromTicketItemId($ticketItemId) {
		$sql = "SELECT queue_item_id FROM queue_item
			WHERE ticket_item_id = $ticketItemId
			LIMIT 1";
		$qi = Celini::newORDO('QueueItem');
		$res = $qi->_execute($sql);
		if ($res && !$res->EOF) {
			$qi->setup($res->fields['queue_item_id']);
		}
		return $qi;
	}

	public function getSourceQueue($ticketItemId) {
		$sql = "SELECT q.type FROM
			queue_item qi INNER JOIN queue q ON qi.queue_id = q.queue_id
			WHERE qi.ticket_item_id = $ticketItemId";
		$res = $this->_execute($sql);
		return $res->fields['type'];
	}

	public function updateQueue($ticketItemId, $destQueueId) {
		$sql = "UPDATE queue_item SET start_waiting = NOW(), queue_id = $destQueueId WHERE ticket_item_id = $ticketItemId";
		$this->_execute($sql);
	}

	public function add($ticketItemId, $queueId) {
		if ($this->isExistant($ticketItemId)) {
			return false;
		}

		$obj = Celini::newORDO('TicketItem', $ticketItemId);
		$roomId = $obj->get('room_id');
		$ticketId = $obj->get('ticket_id');
		/**
		 * CASHIER queue is a special queue. The room_id is NOT where cashier stays
		 * (the place that patient has to be here for payment) . So if we add the roomId to WHERE
		 * clause, maybe we will produce a unexpected result.
		 *
		 * The solutions are:
		 * 1. Currently, when moving a ticket item to cashier queue, we don't specify
		 * exactly which payment room patient is to be there (we assume only one payment
		 * room is available). This way we cannot have many rooms for payment.collection
		 *
		 * 2. it requires to specify exactly which payment room patient is to be when there
		 * is a move to it. (It may be defined is database as a mapping or doctor must
		 * clearly select the exact payment room for patient). This way moves us to a flexible payment
		 * collection that we can support many rooms for collecting payment.
		 *
		 * IMPLEMENTED SOLUTION 1
		 */
		$queue = Celini::newORDO('Queue', $queueId);
		if ($queue->get('type') == AbsQueue::CASHIER) {
			$conf = Celini::configInstance();
			$roomId = $conf->get('default_cashier_room_id');
		}

		$ticketId = $obj->get('ticket_id');
		$ticket = Celini::newORDO('Ticket', $ticketId);
		$patientId = $ticket->get('patient_id');

		$data = array(
			'patient_id'	=> $patientId,
			'ticket_item_id'=> $ticketItemId,
			'queue_id'		=> $queueId,
			'room_id'		=> $roomId,
			'ticket_id'		=> $ticketId);
		$this->populateArray($data);
		$this->persist();

		$sql = "update queue_item set start_waiting = NOW() where queue_item_id = " . $this->get_id();
		$this->_execute($sql);
		return true;
	}

	public function delete($ticketItemId) {
		$sql = "DELETE FROM queue_item
				WHERE ticket_item_id = $ticketItemId";
		$this->_execute($sql);
	}

	public function getAll($queueId, $roomId, $departmentId) {
	    $field = L10nHelper::changeField(L10nHelper::getLocale(), 'name');
		$ds = new Datasource_sql();		
		$sql = array(
			'cols' 	=> "QI.queue_item_id, QI.ticket_item_id, QI.patient_id,	QI.holder_id,
					PA.patient_code patient_code, PE.name patient_name, PA_E.receptionist_name,
					PA_E.entry_time entry_time,
					TIMESTAMPDIFF(MINUTE, QI.start_waiting, NOW()) waiting_time,
					R.$field room_name",
			'from'	=> "queue_item QI
				INNER JOIN patient PA ON QI.patient_id = PA.person_id
				INNER JOIN person PE ON QI.patient_id = PE.person_id
				INNER JOIN patient_entry PA_E ON QI.ticket_id = PA_E.ticket_id
				INNER JOIN room R ON QI.room_id = R.room_id
				INNER JOIN department D ON R.department_id = D.department_id",
			'where'	=> "QI.queue_id = $queueId",
			'orderby'	=> "QI.start_waiting"
			);

		if (is_array($roomId)){
			$rooms	=	"";
			foreach($roomId as $value){
				$rooms	=	$rooms. $value. ",";
			}
			$rooms	=	substr($rooms, 0 , strlen($rooms)-1);
			$sql['where'] .= " AND QI.room_id IN (". $rooms. ")";
		}
		else {
			$sql['where'] .= " AND QI.room_id = $roomId";
		}
		/*else if($departmentId) {
			// Empty roomId means selecting all room of the department
			// We shoule ignore the cashier queue
			$conf = Celini::configInstance();
			$cashierRoomId = $conf->get('default_cashier_room_id');
			$sql['where'] .= " AND D.department_id = $departmentId
								AND QI.room_id != $cashierRoomId";
		}*/
		$ds->setup($this->_db, $sql);
		return $ds->toArray();
	}

	public function isExistant($ticketItemId, $queueId = 0) {
		$sql = "select queue_item_id from queue_item
					where ticket_item_id = $ticketItemId";
		if (!empty($queueId)) {
			$sql .= " and queue_id = $queueId";
		}

		$res = $this->_execute($sql);
		if ($res && !$res->EOF) {
			return true;
		}
		return false;
	}

	function persist($startWaiting='') {
		parent::persist();
		if (empty($startWaiting)) {
			$startWaiting = 'NOW()';
		}
		$sql = "UPDATE $this->_table SET start_waiting = $startWaiting WHERE ticket_item_id = $this->ticket_item_id";
		$this->_execute($sql);
	}

	public function getCurrentServiceItem($ticketId) {
		$serviceType   =  TicketItem::SERVICE_TYPE;
		$compositeType =  TicketItem::COMPOSITE_SERVICE;
        $sql    =   "SELECT T.ticket_item_id FROM $this->_table T
                    INNER JOIN ticket_item TI ON (T.ticket_item_id=TI.ticket_item_id)
                    WHERE T.ticket_id='$ticketId' AND TI.item_type IN ('$serviceType', '$compositeType')";
        $res    =   $this->_execute($sql);
        if ($res && !$res->EOF) {
            return $res->fields['ticket_item_id'];
        }
        return false;
	}

	public function removeItemsByTicket($ticketId) {
        $sql    =   "DELETE FROM $this->_table WHERE ticket_id='$ticketId'";
        $this->_execute($sql);
	}
	
	public function getPartial($queueId, $roomId, $itemPerPage, $page, $doctorId = 0) {
		$firstItem = ($page - 1) * $itemPerPage;
		
		$ds = new Datasource_sql();
		$sql = array(
			'cols' 		=> "QI.queue_item_id, QI.ticket_item_id, QI.patient_id,	QI.holder_id,
					PA.patient_code patient_code, PE.name patient_name",
			'from'		=> "queue_item QI
				INNER JOIN patient PA ON QI.patient_id = PA.person_id
				INNER JOIN person PE ON QI.patient_id = PE.person_id",
			'where'		=> "QI.queue_id = $queueId AND QI.room_id = $roomId",
			'orderby'	=> "QI.start_waiting",
			'limit'		=> "$firstItem, $itemPerPage"
		);
		if ($doctorId != 0) {
			$sql['where'] .= " AND QI.holder_id = $doctorId";
		}
		$ds->setup($this->_db, $sql);
		return $ds->toArray();
	}
	
	public function countItems($queueId, $roomId, $doctorId = 0) {
		$sql = "SELECT COUNT(queue_item_id) AS total FROM queue_item WHERE queue_id = $queueId AND room_id = $roomId";
		if ($doctorId != 0) {
			$sql .= " AND holder_id = $doctorId";
		}
		$res = $this->_execute($sql);
		return $res->fields['total'];
	}
}
?>
